/**
 *
 */
package com.newer.config.freemarker;

import com.alibaba.druid.util.StringUtils;
import com.newer.dao.bean.sys.User;
import freemarker.core.Environment;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateDirectiveModel;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.utility.DeepUnwrap;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.util.CollectionUtils;

import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Field;
import java.util.Map;

/**
 * shiro判断是否拥有某个属性
 *
 * @author xuntj
 * @create 2018-04-02 9:03
 **/
public class AttributeEqualTag implements TemplateDirectiveModel {

    /**
     * 日志信息打印
     */
    Logger logger = LogManager.getLogger(this.getClass());

    /**
     * Executes this user-defined directive; called by FreeMarker when the user-defined
     * directive is called in the template.
     *
     * @param env      the current processing environment. Note that you can access
     *                 the output {@link Writer Writer} by {@link Environment#getOut()}.
     * @param params   the parameters (if any) passed to the directive as a
     *                 map of key/value pairs where the keys are {@link String}-s and the
     *                 values are {@link TemplateModel} instances. This is never
     *                 <code>null</code>. If you need to convert the template models to POJOs,
     *                 you can use the utility methods in the {@link DeepUnwrap} class.
     * @param loopVars an array that corresponds to the "loop variables", in
     *                 the order as they appear in the directive call. ("Loop variables" are out-parameters
     *                 that are available to the nested body of the directive; see in the Manual.)
     *                 You set the loop variables by writing this array. The length of the array gives the
     *                 number of loop-variables that the caller has specified.
     *                 Never <code>null</code>, but can be a zero-length array.
     * @param body     an object that can be used to render the nested content (body) of
     *                 the directive call. If the directive call has no nested content (i.e., it's like
     *                 &lt;@myDirective /&gt; or &lt;@myDirective&gt;&lt;/@myDirective&gt;), then this will be
     *                 <code>null</code>.
     * @throws TemplateException If any problem occurs that's not an {@link IOException} during writing the template
     *                           output.
     * @throws IOException       When writing the template output fails.
     */
    @Override
    public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) {
        // 获取用户信息
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        if (CollectionUtils.isEmpty(params.keySet())) {
            return;
        }
        try {
            // 获取第一个属性
            if (params.containsKey("eqProperty")) {
                Field field = User.class.getDeclaredField(String.valueOf(params.get("eqProperty")));
                field.setAccessible(true);
                Object value = field.get(user);
                if (value != null) {
                    if (StringUtils.equals(String.valueOf(value), String.valueOf(params.get("eqValue")))) {
                        body.render(env.getOut());
                    }
                }
            }
        } catch (Exception e) {
            logger.error("Shiro标签判断用户属性信息失败,失败原因:" + e.getCause(), e);
        }

    }
}
